#include <math/OOB.h>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>

namespace math
{

OOB::OOB(const glm::vec3& position, const glm::vec2& front, const glm::vec2& right, float height) :
    _position(position), _front(front), _right(right), _height(height)
{}

//! @brief 获取 vec 对 base 投影的长度
float OOB::projectionLength(const glm::vec2& vec, const glm::vec2& base)
{
    float dotValue = glm::dot(vec, base);
    return glm::abs( dotValue / glm::length(base) );
}

//! @brief 获取 front 与 right 对 base 投影长度综合（再加速 base 自身长度）
float OOB::projectionSumLength(const glm::vec2& front, const glm::vec2& right, const glm::vec2& base)
{
    float distance = 0.0;
    distance += glm::length(base);
    distance += OOB::projectionLength(front, base);
    distance += OOB::projectionLength(right, base);

    return distance;
}

//! @brief 碰撞检测
bool OOB::collide(const OOB& obj1, const OOB& obj2)
{
    // 判断高度
    if (obj1._position.y > obj2._position.y && 
        (obj1._position.y - obj2._position.y) > (obj1._height + obj2._height))
        return false;
    if (obj1._position.y < obj2._position.y && 
        (obj2._position.y - obj1._position.y) > (obj1._height + obj2._height))
        return false;

    // 水平碰撞检测
    return horizontalCollide(obj1, obj2);
}

//! @brief 水平碰撞检测
bool OOB::horizontalCollide(const OOB& obj1, const OOB& obj2)
{
    float objDistance = sqrt(pow(obj1._position.x - obj2._position.x, 2) + pow(obj1._position.x - obj2._position.x, 2));
    
    // 检测 obj1 的 front 边
    if (OOB::projectionSumLength(obj2._front, obj2._right, obj1._front) < objDistance) 
        return false;

    // 检测 obj1 的 right 边
    if (OOB::projectionSumLength(obj2._front, obj2._right, obj1._right) < objDistance) 
        return false;

    // 检测 obj2 的 front 边
    if (OOB::projectionSumLength(obj1._front, obj1._right, obj2._front) < objDistance) 
        return false;

    // 检测 obj2 的 right 边
    if (OOB::projectionSumLength(obj1._front, obj1._right, obj2._right) < objDistance) 
        return false;

    return true;
}

}